#include "Terrain.h"
#include "GameManager.h"
#include "Column.h"
#include "Bird.h"
#include "GamePlayLayer.h"
#include "Utils.h"

#define COLUMN_VERTICAL_DISTANCE 100
#define COLUMN_HORIZONTAL_DISTANCE 180
#define COLUMN_HEIGHT 320
#define Y_BETTWEN_COLUMN_RANDOM_RANGE 150

Terrain::Terrain()
{
}

Terrain::~Terrain()
{
	columnArray->release();
	bird->release();
}
void Terrain::setCameraX(float x){
	cameraX = x;
	updateGroundPosition();
}

bool Terrain::init(){
	GameObject::init();
	scheduleUpdate();

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	ground1Sprite = CCSprite::createWithSpriteFrameName("Terrain.png");
	ground2Sprite = CCSprite::createWithSpriteFrameName("Terrain.png");
	addChild(ground1Sprite, 1);
	addChild(ground2Sprite, 1);

	groundWidth = ground1Sprite->getContentSize().width;
	groundHeight = ground1Sprite->getContentSize().height*2/3;
	GameManager::getInstance()->groundY = - visibleSize.height/2 + groundHeight;

	columnArray = CCArray::create();
	columnArray->retain();

	bird = Bird::create();
	bird->retain();
	addChild(bird, 3);

	resetGame();

	return true;
}

void Terrain::updateGroundPosition(){
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	ground1Sprite->setPosition(ccp(ground1X - cameraX, -GameManager::getInstance()->visibleSize.height/2 + groundHeight/2));
	ground2Sprite->setPosition(ccp(ground2X - cameraX, -GameManager::getInstance()->visibleSize.height/2 + groundHeight/2));

	if(ground1X + groundWidth/2 < cameraX - visibleSize.width/2)
		ground1X = ground2X + groundWidth - 1;

	if(ground2X + groundWidth/2 < cameraX - visibleSize.width/2)
		ground2X = ground1X + groundWidth - 1;
}

void Terrain::addColumnRandom(float x){
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	float padding = 50;
	float columnCenterY = groundHeight + COLUMN_VERTICAL_DISTANCE/2 + padding + rand() % Y_BETTWEN_COLUMN_RANDOM_RANGE - visibleSize.height/2;

	Column* upColumn = Column::createWithType(CT_UP);
	upColumn->setPosition(ccp(x, columnCenterY - COLUMN_VERTICAL_DISTANCE/2 - COLUMN_HEIGHT/2));
	addChild(upColumn, 0);
	columnArray->addObject(upColumn);

	CCRect bounding = upColumn->boundingBox();
	CCPoint position = upColumn->getPosition();
	CCPoint anchor = upColumn->getAnchorPoint();

	Column* downColumn = Column::createWithType(CT_DOWN);
	downColumn->setPosition(ccp(x, columnCenterY + COLUMN_VERTICAL_DISTANCE/2 + COLUMN_HEIGHT/2));
	addChild(downColumn, 0);
	columnArray->addObject(downColumn);

	lastColumnAdded = x;
}

void Terrain::update(float delta){
	GameObject::update(delta);

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	if(bird->getState() != BS_DIE && bird->getState() != BS_IN_GROUND){
		cameraX += BIRD_VX*delta;
		setCameraX(cameraX);
	}

	bird->updateCameraPosition(cameraX);

	// add column
	if(bird->getState() == BS_FLY){
		if(lastColumnAdded < 0){
			addColumnRandom(cameraX + visibleSize.width);
		}
		else{
			if(lastColumnAdded - cameraX < visibleSize.width){
				addColumnRandom(lastColumnAdded + COLUMN_HORIZONTAL_DISTANCE);
			}
		}
	}

	CCObject* obj;
	CCARRAY_FOREACH(columnArray, obj){
		Column* column = (Column*)obj;

		column->updateCameraPosition(cameraX);

		// check collision with bird
		if(column->boundingBox().intersectsRect(bird->boundingBox()) && bird->getState() == BS_FLY){
			stopGame();
			Utils::playEffect("Hit");
		}

		// add score
		if(column->getType() == CT_UP && column->isPass == false && column->getPositionX() < bird->getPositionX()){
			GameManager::getInstance()->score++;
			Utils::playEffect("Point");
			column->isPass = true;
		}

		// check remove column
		if(column->getPosition().x < cameraX - visibleSize.width){
			column->removeFromParent();
			columnArray->removeObject(column);
		}
	}

	if(bird->getPositionY() < GameManager::getInstance()->groundY && bird->getState() == BS_FLY){
		stopGame();
	}
}

void Terrain::touch(){
	if(bird->getState() == BS_WAIT){
		bird->setState(BS_FLY);
		bird->flyUp();
	}
	else if(bird->getState() == BS_FLY){
		bird->flyUp();
	}
}

void Terrain::stopGame(){
	bird->setState(BS_DIE);

	// save high score if need
	GameManager* gameManager = GameManager::getInstance();
	if(gameManager->score > gameManager->highScore){
		gameManager->saveHighScore(gameManager->score);
	}

	// submit to server
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	Utils::updateTopScoreLeaderboard(gameManager->score);
#endif
}

void Terrain::resetGame(){
	setCameraX(80);

	ground1X = 10;
	ground2X = ground1X + groundWidth-1;
	updateGroundPosition();

	lastColumnAdded = -10000;

	bird->reset();
	GameManager::getInstance()->resetGame();

	CCObject* obj;
	CCARRAY_FOREACH(columnArray, obj){
		Column* column = (Column*)obj;
		column->removeFromParent();
	}
	columnArray->removeAllObjects();
}